package pers.amos.edu.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import pers.amos.edu.common.GlobalResult;
import pers.amos.edu.common.RedisKeyConstant;
import pers.amos.edu.common.WxProperties;
import pers.amos.edu.exception.EducationException;
import pers.amos.edu.exception.ExceptionEnum;
import pers.amos.edu.mapper.UserMapper;
import pers.amos.edu.pojo.User;
import pers.amos.edu.utils.MiniAESUtil;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author amos wong
 * @create 2020-02-01 19:09
 */

@Service
@EnableConfigurationProperties(WxProperties.class)
public class UserService {

    private static final Logger log = LoggerFactory.getLogger(UserService.class);

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private WxProperties wxProperties;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 获取sessionKey和openId
     * 并且对用户加密的个人信息进行解密
     *
     * @param encryptedData
     * @param iv
     * @param code
     * @return
     */
    public GlobalResult decodeUserInfo(String encryptedData, String iv, String code) {
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(iv) || StringUtils.isEmpty(encryptedData)) {
            log.error("[微信授权登录],code为空");
            throw new EducationException(ExceptionEnum.INVALID_PARAMS);
        }
        Map data = sendRequestToWeChat(code);
        Object errorCode = data.get("errcode");
        if (errorCode != null) {
            log.info("授权码错误");
            throw new EducationException(ExceptionEnum.CODE_INVALID);
        }
        String sessionKey = (String) data.get("session_key");
        String openId = (String) data.get("openid");
        Boolean isMember = redisTemplate.opsForSet().isMember(RedisKeyConstant.USER_INFO, openId);
        if (isMember) {
            return new GlobalResult(200, "授权成功", userMapper.getUserInfoByOpenId(openId));
        }
        log.info("获取一切数据正常");
        try {
            String result = MiniAESUtil.wxDecrypt(encryptedData, sessionKey, iv);
            log.info("解密正常");
            if (StringUtils.isNotEmpty(result)) {
                JSONObject userInfoJSON = JSON.parseObject(result);
                User user = new User();
                user.setOpenId(openId);
                user.setUserType(1);  //普通用户设为1 // 特殊用户2
                user.setSessionKey(sessionKey);
                user.setNickName((String) userInfoJSON.get("nickName"));
                user.setGender((Integer) userInfoJSON.get("gender"));
                user.setCity((String) userInfoJSON.get("city"));
                user.setProvince((String) userInfoJSON.get("province"));
                user.setCountry((String) userInfoJSON.get("country"));
                user.setAvatarUrl((String) userInfoJSON.get("avatarUrl"));
                user.setCreateTime(new Date());
                user.setLastVisitTime(new Date());
                User updateUser = userMapper.getUserInfoByOpenId(openId);
                // 更新操作
                if (updateUser != null) {
                    userMapper.updateByPrimaryKeySelective(user);
                    redisTemplate.opsForSet().add(RedisKeyConstant.USER_INFO + openId, 1);
                    return new GlobalResult(HttpStatus.OK.value(), "授权成功", updateUser);
                }
                userMapper.insert(user);
                redisTemplate.opsForSet().add(RedisKeyConstant.USER_INFO, openId);
            }
            throw new EducationException(ExceptionEnum.DECODE_ERROR);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new GlobalResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), "授权失败", null);
    }

    @Transactional
    public GlobalResult saveUserPhone(String openId, String encryptedData, String sessionKey, String iv) {
        User user = userMapper.selectByPrimaryKey(openId);
        if (user == null) {
            return new GlobalResult(500, "用户未登录", null);
        }
        Object result = MiniAESUtil.getPhoneNumber(encryptedData, sessionKey, iv);
        HashMap<String, String> map = JSONObject.parseObject(JSON.toJSONString(result), HashMap.class);
        String phoneNumber = map.get("phoneNumber");
        user.setPhone(phoneNumber);
        userMapper.updateByPrimaryKeySelective(user);
        return new GlobalResult(200, "保存手机号成功", null);
    }

    public String getUserOpenId(String code) {
        Map data = sendRequestToWeChat(code);
        String openId = (String) data.get("openid");
        return openId;
    }

    private Map sendRequestToWeChat(String code) {
        log.info("=======开始微信请求========");
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid="
                + wxProperties.getAppId() + "&secret=" + wxProperties.getAppSecret()
                + "&js_code=" + code + "&grant_type=authorization_code";
        ResponseEntity<Map> responseBody = restTemplate.getForEntity(url, Map.class);
        log.info("=======微信请求正常========");
        Map data = responseBody.getBody();
        log.info("=======获取body正常=======");
        return data;
    }
}